﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.WebControls;
using System.Web.UI;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;

using net.windward.tags;
using net.windward.utils.ado;
using System.Net;
using log4net;
using System.IO;
using Kailua.net.windward.utils;
using System.Collections;

namespace ArrowWebParts
{
    class DashboardEditorPart : EditorPart
    {
        #region fields

        TextBox refreshTimeTextBox;
        RequiredFieldValidator refreshTimeTextBoxReqValidator;
        RegularExpressionValidator refreshTimeTextBoxRegExValidator;
        TextBox frameHeightTextBox;
        RequiredFieldValidator frameHeightTextBoxReqValidator;
        RegularExpressionValidator frameHeightTextBoxRegExValidator;
        CheckBox scrollbarDisplayCheckBox;

        DropDownList sitesDropDownList;
        DropDownList documentLibrariesDropDownList;
        DropDownList filesDropDownList;
        Label variableStatusLabel;
        Table variableTable;
        Label[] variableNameLabelArray;
        Label[] variableRequiredLabelArray;
        Label[] variableTypeLabelArray;
        TextBox[] variableValueTextBoxArray;
        DropDownList[] variableValueDropDownListArray;
        Label statusLabel;

        private static ILog log = LogManager.GetLogger(typeof(DashboardEditorPart));

        #endregion

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            if (log.IsDebugEnabled)
                log.Debug("Creating child controls.");

            try
            {
                Title = "Arrow Dashboard Properties";

                ToolPane pane = Zone as ToolPane;
                if (pane != null)
                    pane.Cancel.CausesValidation = false;

                generateAndAddEditorPartTextBox("Refresh Time (seconds)", "Input the amount of time between refreshes.  Input 0 to have it not refresh automatically.", out refreshTimeTextBox);
                refreshTimeTextBox.ID = "refreshTimeTextBox";
                refreshTimeTextBoxReqValidator = new RequiredFieldValidator();
                refreshTimeTextBoxReqValidator.ControlToValidate = "refreshTimeTextBox";
                refreshTimeTextBoxReqValidator.Display = ValidatorDisplay.Dynamic;
                refreshTimeTextBoxReqValidator.Text = "* Enter an positive integer (0, 1, 2, 3...)";
                Controls.Add(refreshTimeTextBoxReqValidator);
                refreshTimeTextBoxRegExValidator = new RegularExpressionValidator();
                refreshTimeTextBoxRegExValidator.ControlToValidate = "refreshTimeTextBox";
                refreshTimeTextBoxRegExValidator.Display = ValidatorDisplay.Dynamic;
                refreshTimeTextBoxRegExValidator.ValidationExpression = @"\d+";
                refreshTimeTextBoxRegExValidator.Text = "* Enter an positive integer (0, 1, 2, 3...)";
                Controls.Add(refreshTimeTextBoxRegExValidator);

                Controls.Add(new LiteralControl("<br/><DIV class=\"UserDottedLine\" width=\"100%\"></DIV>"));
                generateAndAddEditorPartTextBox("Dashboard Widget Height (pixels)", "Input the desired height of the widget.  Input 0 to have it attempt to automatically size the widget.", out frameHeightTextBox);
                frameHeightTextBox.ID = "frameHeightTextBox";
                frameHeightTextBoxReqValidator = new RequiredFieldValidator();
                frameHeightTextBoxReqValidator.ControlToValidate = "frameHeightTextBox";
                frameHeightTextBoxReqValidator.Display = ValidatorDisplay.Dynamic;
                frameHeightTextBoxReqValidator.Text = "* Enter an positive integer (0, 1, 2, 3...)";
                Controls.Add(frameHeightTextBoxReqValidator);
                frameHeightTextBoxRegExValidator = new RegularExpressionValidator();
                frameHeightTextBoxRegExValidator.ControlToValidate = "frameHeightTextBox";
                frameHeightTextBoxRegExValidator.Display = ValidatorDisplay.Dynamic;
                frameHeightTextBoxRegExValidator.ValidationExpression = @"\d+";
                frameHeightTextBoxRegExValidator.Text = "* Enter an positive integer (0, 1, 2, 3...)";
                Controls.Add(frameHeightTextBoxRegExValidator);

                Controls.Add(new LiteralControl("<br/><DIV class=\"UserDottedLine\" width=\"100%\"></DIV>"));
                // function to create and add the checkbox
                generateAndAddEditorPartCheckBox("Display scrollbars?", "Check to enable scroll bars.  Uncheck to disable scrollbars.", out scrollbarDisplayCheckBox);

                /*Controls.Add(new LiteralControl("<br/><DIV class=\"UserDottedLine\" width=\"100%\"></DIV>"));
                generateAndAddEditorPartTextBox("Widget URL", "URL where the widget contents can be displayed.  Use the below URL Generator to populate this.", out urlTextBox);
                urlTextBox.ID = "urlTextBox";
                urlTextBoxRequiredFieldValidator = new RequiredFieldValidator();
                urlTextBoxRequiredFieldValidator.Display = ValidatorDisplay.Dynamic;
                urlTextBoxRequiredFieldValidator.ErrorMessage = "* Enter a URL";
                urlTextBoxRequiredFieldValidator.Text = "* Enter a URL";
                urlTextBoxRequiredFieldValidator.ControlToValidate = "urlTextBox";
                Controls.Add(urlTextBoxRequiredFieldValidator);*/

                Controls.Add(new LiteralControl("<br/><DIV class=\"UserDottedLine\" width=\"100%\"></DIV>"));
                Controls.Add(new LiteralControl("<DIV class=\"UserSectionHead\">"));
                Controls.Add(new Label { Text = "Select Report Definition/Template", ToolTip = "This tools helps you select a report definition/template and set variable values." });
                Controls.Add(new LiteralControl("<br/><br/>"));
                Controls.Add(new LiteralControl("</DIV>"));

                Controls.Add(new LiteralControl("<u>1. Locate the report definition/template file</u><br/>"));

                Controls.Add(new LiteralControl("Site<br/>"));
                sitesDropDownList = new DropDownList();
                sitesDropDownList.SelectedIndexChanged += new EventHandler(sitesDropDownList_SelectedIndexChanged);
                sitesDropDownList.AutoPostBack = true;
                SPSite oSiteCollection = SPContext.Current.Site;

                SPWebCollection collWebsite = ArrowUtils.GetSPWebCollectionFromCurrentSite();
                foreach (SPWeb oWebsite in collWebsite)
                {
                    sitesDropDownList.Items.Add(new ListItem(oWebsite.Title, oWebsite.ID.ToString()));
                    oWebsite.Dispose();
                }

                sitesDropDownList.SelectedIndex = sitesDropDownList.Items.IndexOf(sitesDropDownList.Items.FindByValue(SPContext.Current.Web.ID.ToString()));
                Controls.Add(sitesDropDownList);

                Controls.Add(new LiteralControl("<br/>Document Library<br/>"));
                documentLibrariesDropDownList = new DropDownList();
                documentLibrariesDropDownList.SelectedIndexChanged += new EventHandler(documentLibrariesDropDownList_SelectedIndexChanged);
                documentLibrariesDropDownList.AutoPostBack = true;
                Controls.Add(documentLibrariesDropDownList);

                Controls.Add(new LiteralControl("<br/>File<br/>"));
                filesDropDownList = new DropDownList();
                filesDropDownList.SelectedIndexChanged += new EventHandler(filesDropDownList_SelectedIndexChanged);
                filesDropDownList.AutoPostBack = true;
                Controls.Add(filesDropDownList);

                Controls.Add(new LiteralControl("<br/><br/><u>2. Set variables:</u><br/>"));
                variableStatusLabel = new Label();
                Controls.Add(variableStatusLabel);

                int maxVars = 50;
                variableTable = createEmptyTable(1 + maxVars, 4, 0, 125);
                variableTable.Rows[0].Cells[0].Controls.Add(new LiteralControl("<u>Variable Name</u>"));
                variableTable.Rows[0].Cells[1].Controls.Add(new LiteralControl("<u>Required?</u>"));
                variableTable.Rows[0].Cells[2].Controls.Add(new LiteralControl("<u>Type</u>"));
                variableTable.Rows[0].Cells[3].Controls.Add(new LiteralControl("<u>Variable Value</u>"));
                variableNameLabelArray = new Label[maxVars];
                variableRequiredLabelArray = new Label[maxVars];
                variableTypeLabelArray = new Label[maxVars];
                variableValueTextBoxArray = new TextBox[maxVars];
                variableValueDropDownListArray = new DropDownList[maxVars];
                for (int j = 0; j < variableNameLabelArray.Length; j++)
                {
                    variableNameLabelArray[j] = new Label();
                    variableNameLabelArray[j].Text = "Blah blah blah";
                    variableNameLabelArray[j].Visible = false;
                    variableTable.Rows[1 + j].Cells[0].Controls.Add(variableNameLabelArray[j]);

                    variableRequiredLabelArray[j] = new Label();
                    variableRequiredLabelArray[j].Visible = false;
                    variableTable.Rows[1 + j].Cells[1].Controls.Add(variableRequiredLabelArray[j]);

                    variableTypeLabelArray[j] = new Label();
                    variableTypeLabelArray[j].Visible = false;
                    variableTable.Rows[1 + j].Cells[2].Controls.Add(variableTypeLabelArray[j]);

                    variableValueTextBoxArray[j] = new TextBox();
                    variableValueTextBoxArray[j].Visible = false;
                    variableTable.Rows[1 + j].Cells[3].Controls.Add(variableValueTextBoxArray[j]);

                    variableValueDropDownListArray[j] = new DropDownList();
                    variableValueDropDownListArray[j].Visible = false;
                    variableTable.Rows[1 + j].Cells[3].Controls.Add(variableValueDropDownListArray[j]);
                }
                variableTable.Visible = false;
                Controls.Add(variableTable);

                //Controls.Add(new LiteralControl("<br/>"));
                //Controls.Add(new LiteralControl("<br/>"));

                statusLabel = new Label();
                statusLabel.Visible = false;
                Controls.Add(statusLabel);

                sitesDropDownList_SelectedIndexChanged(null, null);
            }
            catch (Exception ex)
            {
                ArrowUtils.LogFatalException(log, ex);
                Controls.Clear();
                Controls.Add(new LiteralControl(string.Format("There was an error creating the dashboard editor part: {0}", ex.Message)));
                return;
            }

            if (log.IsDebugEnabled)
                log.Debug("Finished creating child controls.");
        }

        private void generateAndAddEditorPartTextBox(string propertyName, string toolTip, out TextBox tex)
        {
            Controls.Add(new LiteralControl("<DIV class=\"UserSectionHead\">"));
            Controls.Add(new Label { Text = propertyName, ToolTip = toolTip });
            Controls.Add(new LiteralControl("</DIV>"));
            Controls.Add(new LiteralControl("<DIV class=\"UserSectionBody\">"));
            Controls.Add(new LiteralControl("<DIV class=\"UserControlGroup\">"));
            Controls.Add(new LiteralControl("<NOBR>"));
            tex = new TextBox();
            tex.CssClass = "UserInput";
            Controls.Add(tex);
            Controls.Add(new LiteralControl("<NOBR>"));
            Controls.Add(new LiteralControl("<DIV class=\"UserSectionBody\">"));
            Controls.Add(new LiteralControl("<DIV class=\"UserControlGroup\">"));
        }

        private void generateAndAddEditorPartCheckBox(string propertyName, string toolTip, out CheckBox che)
        {
            Controls.Add(new LiteralControl("<DIV class=\"UserSectionHead\">"));
            Controls.Add(new Label { Text = propertyName, ToolTip = toolTip });
            Controls.Add(new LiteralControl("</DIV>"));
            Controls.Add(new LiteralControl("<DIV class=\"UserSectionBody\">"));
            Controls.Add(new LiteralControl("<DIV class=\"UserControlGroup\">"));
            Controls.Add(new LiteralControl("<NOBR>"));
            che = new CheckBox();
            che.CssClass = "UserInput";
            Controls.Add(che);
            Controls.Add(new LiteralControl("<NOBR>"));
            Controls.Add(new LiteralControl("<DIV class=\"UserSectionBody\">"));
            Controls.Add(new LiteralControl("<DIV class=\"UserControlGroup\">"));
        }

        #region delegate functions

        void sitesDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            documentLibrariesDropDownList.Items.Clear();
            if (sitesDropDownList.Items.Count != 0)
            {
                SPWebCollection collWebsite = ArrowUtils.GetSPWebCollectionFromCurrentSite();
                Guid siteGuid = new Guid(sitesDropDownList.SelectedValue);
                SPWeb site = collWebsite[siteGuid];

                foreach (SPList list in site.Lists)
                {
                    if (list is SPDocumentLibrary && !list.Hidden)
                    {
                        documentLibrariesDropDownList.Items.Add(new ListItem(list.Title, list.ID.ToString()));
                    }
                }
            }
            documentLibrariesDropDownList_SelectedIndexChanged(null, null);
        }

        void documentLibrariesDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            filesDropDownList.Items.Clear();
            if (documentLibrariesDropDownList.Items.Count != 0)
            {
                SPWebCollection collWebsite = ArrowUtils.GetSPWebCollectionFromCurrentSite();
                Guid siteGuid = new Guid(sitesDropDownList.SelectedValue);
                SPWeb site = collWebsite[siteGuid];

                Guid libraryID = new Guid(documentLibrariesDropDownList.SelectedValue);
                SPDocumentLibrary library = (SPDocumentLibrary)site.Lists[libraryID];

                ArrayList sortedItems = new ArrayList();
                foreach (SPListItem item in library.Items)
                {
                    SPFile file = item.File;
                    if (file.Name.EndsWith(".reportdef") || file.Name.EndsWith(".wrf") || file.Name.EndsWith(".docx") || file.Name.EndsWith(".xlsx") || file.Name.EndsWith(".pptx"))
                        sortedItems.Add(file);
                }
                sortedItems.Sort(new ArrowUtils.SPFileComparer());

                foreach (SPFile file in sortedItems)
                    filesDropDownList.Items.Add(new ListItem(file.Name, file.UniqueId.ToString()));
            }

            if (documentLibrariesDropDownList.Items.Count == 0)
            {
                documentLibrariesDropDownList.Items.Add(new ListItem("<None>", ""));
                filesDropDownList.Items.Add(new ListItem("<None>", ""));
            }
            else if (filesDropDownList.Items.Count == 0)
            {
                filesDropDownList.Items.Add(new ListItem("<None>", ""));
            }

            if (sitesDropDownList.Items.Count == 0)
            {
                // Not sure how this would be possible, but just in case.
                sitesDropDownList.Items.Add(new ListItem("<None>", ""));
            }

            filesDropDownList_SelectedIndexChanged(null, null);
        }

        void filesDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (filesDropDownList.SelectedValue != "") // We have a report definition or template file
                {
                    // Display variables!!!
                    SPSite oSiteCollection = SPContext.Current.Site;

                    SPWebCollection collWebsite = ArrowUtils.GetSPWebCollectionFromCurrentSite();
                    Guid siteGuid = new Guid(sitesDropDownList.SelectedValue);
                    SPWeb site = collWebsite[siteGuid];

                    Guid libraryID = new Guid(documentLibrariesDropDownList.SelectedValue);
                    SPDocumentLibrary library = (SPDocumentLibrary) site.Lists[libraryID];

                    Guid fileID = new Guid(filesDropDownList.SelectedValue);
                    SPFile file = library.Items[fileID].File;

                    string relativePath = file.ServerRelativeUrl;
                    string absolutePath = SPContext.Current.Site.MakeFullUrl(relativePath);

                    //ReportDefinition rai = new ReportDefinition(absolutePath);
                    string error;
                    ReportDefinition rai = ArrowUtils.GetReportDefFromFile(absolutePath, out error);
                    if (error != "")
                        return;

                    const string WR_LOGIN = "WR_LOGIN";
                    const string WR_USER = "WR_USER";
                    int ind_WR_LOGIN = -1;
                    int ind_WR_USER = -1;
                    for (int i = 0; i < rai.variableNameArray.Length; i++)
                    {
                        if (rai.variableNameArray[i].Equals(WR_LOGIN))
                            ind_WR_LOGIN = i;
                        else if (rai.variableNameArray[i].Equals(WR_USER))
                            ind_WR_USER = i;
                    }

                    int numVars = ArrowUtils.GetNumVarsForDisplay(rai);
                    if (numVars == 0)
                    {
                        variableStatusLabel.Text = "No variables found.";
                        statusLabel.Text = "Press the button below to populate your widget URL.";
                        variableTable.Visible = false;
                    }
                    else // There are variables
                    {
                        statusLabel.Text = "Press the button below when ready.";
                        for (int i = 0; i < numVars; i++)
                        {
                            variableNameLabelArray[i].Visible = false;
                            variableRequiredLabelArray[i].Visible = false;
                            variableTypeLabelArray[i].Visible = false;
                            variableValueTextBoxArray[i].Visible = false;
                            variableValueDropDownListArray[i].Visible = false;
                        }

                        int raiVarInd = 0;
                        for (int i = 0; i < numVars; i++)
                        {
                            while (raiVarInd == ind_WR_LOGIN || raiVarInd == ind_WR_USER)
                            {
                                raiVarInd++;
                            }
                            if (raiVarInd >= rai.variableNameArray.Length)
                            {
                                //bugbug: this shouldn't happen
                                Trap.trap();
                                if (log.IsDebugEnabled)
                                    log.Debug("raiVarInd >= rai.variableNameArray.Length returned true");
                            }

                            variableNameLabelArray[i].Visible = true;
                            variableNameLabelArray[i].Text = rai.variableNameArray[raiVarInd];

                            variableRequiredLabelArray[i].Visible = true;
                            variableRequiredLabelArray[i].Text = rai.variableRequiredArray[raiVarInd];

                            variableTypeLabelArray[i].Visible = true;
                            variableTypeLabelArray[i].Text = rai.variableTypeArray[raiVarInd];

                            if (variableTypeLabelArray[i].Text == "Select")
                            {
                                // Populate dropdownlist
                                variableValueDropDownListArray[i].Visible = true;

                                string nameToSearch = rai.variableDataNameArray[raiVarInd];
                                DataDefinition dsInfo = null;
                                for (int j = 0; j < rai.dataSourceNameArray.Length; j++)
                                {
                                    if (rai.dataSourceNameArray[j] == nameToSearch)
                                    {
                                        string pathOfDataSpec = rai.dataSourcePathArray[j];
                                        dsInfo = new DataDefinition(pathOfDataSpec);
                                        break;
                                    }
                                }
                                if (dsInfo == null)
                                    throw new FileNotFoundException(string.Format("Could not find datadef entry named {0}.", nameToSearch));

                                object[] queryResult = ArrowUtils.getSelectParameterObjects(rai.variableDataNameArray[raiVarInd], dsInfo,
                                                                     rai.variableSelectCountArray[raiVarInd],
                                                                     rai.variableSelectAllArray[raiVarInd]);
                                foreach (object ob in queryResult)
                                {
                                    string input = ob.ToString();
                                    variableValueDropDownListArray[i].Items.Add(new ListItem(input, input));
                                }
                                if (variableValueDropDownListArray[i].Items.Count == 0)
                                {
                                    variableValueDropDownListArray[i].Items.Add(new ListItem("<none>", ""));
                                }
                                //set default value
                                string defaultValue = rai.variableDefaultArray[raiVarInd];
                                for (int j = 0; j < variableValueDropDownListArray.Length; j++)
                                {
                                    if (variableValueDropDownListArray[i].Items[j].Value == defaultValue)
                                    {
                                        variableValueDropDownListArray[i].SelectedIndex = j;
                                        break;
                                    }
                                }
                            }
                            else
                            {
                                variableValueTextBoxArray[i].Visible = true;
                                variableValueTextBoxArray[i].Text = rai.variableDefaultArray[raiVarInd];
                            }

                            raiVarInd++;
                        }
                        variableStatusLabel.Text = "Input variable values below.";
                        variableTable.Visible = true;
                    }

                }
                else
                {
                    variableStatusLabel.Text = "No variables found.";
                    statusLabel.Text = "Select a report definition or template.";
                    variableTable.Visible = false;
                }
            }
            catch(Exception ex)
            {
                variableStatusLabel.Text = "No variables found.";
                statusLabel.Text = "Error: invalid report definition or template.";
                variableTable.Visible = false;
                return;
            }
        }

        #endregion

        private string generateRptDefPath()
        {
            SPSite oSiteCollection = SPContext.Current.Site;

            SPWebCollection collWebsite = ArrowUtils.GetSPWebCollectionFromCurrentSite();
            Guid siteGuid = new Guid(sitesDropDownList.SelectedValue);
            SPWeb site = collWebsite[siteGuid];

            Guid libraryID = new Guid(documentLibrariesDropDownList.SelectedValue);
            SPDocumentLibrary library = (SPDocumentLibrary)site.Lists[libraryID];

            Guid fileID = new Guid(filesDropDownList.SelectedValue);
            SPFile file = library.Items[fileID].File;

            string relativePath = file.ServerRelativeUrl;
            string absolutePath = SPContext.Current.Site.MakeFullUrl(relativePath);

            return absolutePath;

        }

        public override void SyncChanges()
        {
            if (log.IsDebugEnabled)
                log.Debug("Syncing changes.");

            try
            {
                this.EnsureChildControls();
                DashboardWebPart sourcePart = (DashboardWebPart)this.WebPartToEdit;
                refreshTimeTextBox.Text = sourcePart.RefreshTime.ToString();
                frameHeightTextBox.Text = sourcePart.FrameHeight.ToString();
                scrollbarDisplayCheckBox.Checked = sourcePart.ScrollbarDisplay;

                if (sourcePart.SiteGuid != Guid.Empty)
                {
                    if (sitesDropDownList.Items.FindByValue(sourcePart.SiteGuid.ToString()) != null)
                    {
                        sitesDropDownList.SelectedIndex = sitesDropDownList.Items.IndexOf(sitesDropDownList.Items.FindByValue(sourcePart.SiteGuid.ToString()));
                        sitesDropDownList_SelectedIndexChanged(null, null);

                        if (documentLibrariesDropDownList.Items.FindByValue(sourcePart.DocLibGuid.ToString()) != null)
                        {
                            documentLibrariesDropDownList.SelectedIndex = documentLibrariesDropDownList.Items.IndexOf(documentLibrariesDropDownList.Items.FindByValue(sourcePart.DocLibGuid.ToString()));
                            documentLibrariesDropDownList_SelectedIndexChanged(null, null);

                            if (filesDropDownList.Items.FindByValue(sourcePart.FileGuid.ToString()) != null)
                            {
                                filesDropDownList.SelectedIndex = filesDropDownList.Items.IndexOf(filesDropDownList.Items.FindByValue(sourcePart.FileGuid.ToString()));
                                filesDropDownList_SelectedIndexChanged(null, null);

                                string absoluteRptDefPath = generateRptDefPath();
                                string errorMsg;
                                ReportDefinition rai = ArrowUtils.GetReportDefFromFile(absoluteRptDefPath, out errorMsg);
                                
                                const string WR_LOGIN = "WR_LOGIN";
                                const string WR_USER = "WR_USER";
                                int ind_WR_LOGIN = -1;
                                int ind_WR_USER = -1;
                                for (int i = 0; i < rai.variableNameArray.Length; i++)
                                {
                                    if (rai.variableNameArray[i].Equals(WR_LOGIN))
                                        ind_WR_LOGIN = i;
                                    else if (rai.variableNameArray[i].Equals(WR_USER))
                                        ind_WR_USER = i;
                                }
                                int numVars = ArrowUtils.GetNumVarsForDisplay(rai);
                                int raiVarInd = 0;
                                for (int i = 0; i < numVars; i++)
                                {
                                    while (raiVarInd == ind_WR_LOGIN || raiVarInd == ind_WR_USER)
                                    {
                                        raiVarInd++;
                                    }
                                    if (raiVarInd >= rai.variableNameArray.Length)
                                    {
                                        //bugbug: this shouldn't happen
                                        Trap.trap();
                                        if (log.IsDebugEnabled)
                                            log.Debug("raiVarInd >= rai.variableNameArray.Length returned true");
                                    }

                                    string value;
                                    if (sourcePart.DashboardVariables.TryGetValue(rai.variableNameArray[raiVarInd], out value))
                                    {
                                        if (rai.variableTypeArray[raiVarInd] == "Select")
                                        {
                                            if (variableValueDropDownListArray[i].Items.FindByText(rai.variableNameArray[raiVarInd]) != null)
                                                variableValueDropDownListArray[i].Items.IndexOf(variableValueDropDownListArray[i].Items.FindByText(rai.variableNameArray[raiVarInd]));
                                        }
                                        else
                                            variableValueTextBoxArray[i].Text = value;
                                    }

                                    raiVarInd++;
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ArrowUtils.LogFatalException(log, ex);
                Controls.Clear();
                Controls.Add(new LiteralControl(string.Format("There was an error syncing changes: {0}", ex.Message)));
                return;
            }

            if (log.IsDebugEnabled)
                log.Debug("Finished syncing changes.");
        }

        public override bool ApplyChanges()
        {
            if (log.IsDebugEnabled)
                log.Debug("Applying changes.");

            try
            {
                this.EnsureChildControls();
                DashboardWebPart targetPart = (DashboardWebPart)this.WebPartToEdit;
                if (targetPart != null)
                {
                    //targetPart.DisplayUrl = urlTextBox.Text;
                    targetPart.RefreshTime = Convert.ToInt32(refreshTimeTextBox.Text.Trim());
                    targetPart.FrameHeight = Convert.ToInt32(frameHeightTextBox.Text.Trim());
                    targetPart.ScrollbarDisplay = scrollbarDisplayCheckBox.Checked;

                    targetPart.SiteGuid = Guid.Empty;
                    targetPart.DocLibGuid = Guid.Empty;
                    targetPart.DocLibGuid = Guid.Empty;
                    targetPart.DashboardVariables = new Dictionary<string, string>();
                    if (sitesDropDownList.SelectedValue != "")
                    {
                        targetPart.SiteGuid = new Guid(sitesDropDownList.SelectedValue);
                        if (documentLibrariesDropDownList.SelectedValue != "")
                        {
                            targetPart.DocLibGuid = new Guid(documentLibrariesDropDownList.SelectedValue);
                            if (filesDropDownList.SelectedValue != "")
                            {
                                targetPart.FileGuid = new Guid(filesDropDownList.SelectedValue);

                                Dictionary<string, string> variables = new Dictionary<string, string>();
                                string absoluteRptDefPath = generateRptDefPath();
                                string error;
                                ReportDefinition rai = ArrowUtils.GetReportDefFromFile(absoluteRptDefPath, out error);

                                const string WR_LOGIN = "WR_LOGIN";
                                const string WR_USER = "WR_USER";
                                int ind_WR_LOGIN = -1;
                                int ind_WR_USER = -1;
                                for (int i = 0; i < rai.variableNameArray.Length; i++)
                                {
                                    if (rai.variableNameArray[i].Equals(WR_LOGIN))
                                        ind_WR_LOGIN = i;
                                    else if (rai.variableNameArray[i].Equals(WR_USER))
                                        ind_WR_USER = i;
                                }
                                int numVars = ArrowUtils.GetNumVarsForDisplay(rai);
                                int raiVarInd = 0;
                                for (int i = 0; i < numVars; i++)
                                {
                                    while (raiVarInd == ind_WR_LOGIN || raiVarInd == ind_WR_USER)
                                    {
                                        raiVarInd++;
                                    }
                                    if (raiVarInd >= rai.variableNameArray.Length)
                                    {
                                        //bugbug: this shouldn't happen
                                        Trap.trap();
                                        if (log.IsDebugEnabled)
                                            log.Debug("raiVarInd >= rai.variableNameArray.Length returned true");
                                    }

                                    if (rai.variableTypeArray[raiVarInd] == "Select")
                                        variables.Add(rai.variableNameArray[raiVarInd], variableValueDropDownListArray[i].Text.Trim());
                                    else
                                        variables.Add(rai.variableNameArray[raiVarInd], variableValueTextBoxArray[i].Text.Trim());

                                    raiVarInd++;
                                }
                                targetPart.DashboardVariables = variables;

                                // set DisplayUrl
                                string urlString = SPContext.Current.Web.Url;
                                urlString += "/_layouts/DisplayReport.aspx" +
                                    "?rptDef=" + absoluteRptDefPath +
                                    "&format=" + "HTML" +
                                    "&numvars=" + numVars;
                                if (log.IsDebugEnabled)
                                    log.DebugFormat("Dashboard Url Set: {0}", urlString);
                                raiVarInd = 0;
                                for (int i = 0; i < numVars; i++)
                                {
                                    while (raiVarInd == ind_WR_LOGIN || raiVarInd == ind_WR_USER)
                                    {
                                        raiVarInd++;
                                    }
                                    if (raiVarInd >= rai.variableNameArray.Length)
                                    {
                                        //bugbug: this shouldn't happen
                                        Trap.trap();
                                        if (log.IsDebugEnabled)
                                            log.Debug("raiVarInd >= rai.variableNameArray.Length returned true");
                                    }

                                    if (rai.variableTypeArray[raiVarInd] == "Select")
                                        urlString += "&var" + i + "=" + variableValueDropDownListArray[i].Text.Trim();
                                    else
                                        urlString += "&var" + i + "=" + variableValueTextBoxArray[i].Text.Trim();
                                    
                                    raiVarInd++;
                                }
                                targetPart.DisplayUrl = urlString;
                            }
                        }

                    }
                }
                else
                {
                    if (log.IsDebugEnabled)
                        log.Debug("Finished applying changes.");
                    return false;
                }

                if (log.IsDebugEnabled)
                    log.Debug("Finished applying changes.");

                return true;
            }
            catch (Exception ex)
            {
                ArrowUtils.LogFatalException(log, ex);
                Controls.Add(new LiteralControl(string.Format("There was an error applying changes: {0}", ex.Message)));
                return false;
            }
        }

        private Table createEmptyTable(int numRows, int numCols, int rowHeight, int rowWidth)
        {
            Table t = new Table();
            for (int i = 0; i < numRows; i++)
            {
                TableRow r = new TableRow();

                for (int j = 0; j < numCols; j++)
                {
                    TableCell c = new TableCell();
                    c.Height = rowHeight;
                    c.VerticalAlign = VerticalAlign.Top;
                    r.Cells.Add(c);
                }
                r.Width = rowWidth;
                t.Rows.Add(r);
            }
            return t;
        }
    }
}
